// 需求：对已经开发好的项目中的任何一个类，创建实例时，
// 打印日志信息
// 输出哪一个类被创建了，并输出传递了哪些参数信息

// 泛型工厂类继承装饰器的好处：
// 被装饰的类，实际接收的是它的子类，可以在子类中添加特有的属性与方法。方便类的实力在任何时候调用。而传统的类装饰器，只在装饰上去时，才会触发一次的。

function LoggerInfoDecorator(param: any) {
  // 为什么要定义一个构造函数类型的泛型T
  // 因为如果targetClass为any类型，则LoggerSonClass类继承的是any类型，与目标类Test不兼容
  // 类装饰器底层中 Test = decorator(targetinfo) || targetinfo，而decorator就是LoggerInfoDecorator闭包函数。
  // 所以闭包返回的类，必须是目标类(Test)的兼容类型。
  // 所以方法参数定义为继承了通用构造函数类型的泛型T，因为泛型是定义时不确定类型，调用时（使用时）确定类型的语法机制。
  return function Decorator<T extends { new (...args: any): any }>(targetClass: T) {
    class LoggerSonClass extends targetClass {
      constructor(...args: any) {
        super(...args)
        console.log("日志信息......targetClass: ", targetClass.name)
      }
      saySonClass() {
        console.log("我是子类：", LoggerSonClass.name)
      }
    }
    return LoggerSonClass
  }
}

// 2.目标类
@LoggerInfoDecorator(Test)
class Test {
  name!: string;
  age!: string;
  constructor(name: string) {
    this.name = name
  }
  eat() {
    console.log(this.name, "吃饭");
  }
}
let test: any = new Test("张三")  // 日志信息......targetClass:  Test
test.saySonClass()
export {}